#include "BLE.hpp"
#include "apm32a10x_gpio.h"
#include "apm32a10x_usart.h"
#include "apm32a10x_misc.h"
#include "system.h"

#include "stdio.h"
#include "string.h"
#include <stdlib.h>
#include <time.h>

#include "Configuration.hpp"
#include "CommProtocol.hpp"
#include "fault_info.hpp"
extern FaultInfo *faultinfo;

/* BLE UART2 TX-PA2 RX-PA3 MOD-PC3 RST-PC4 */
static unsigned char __usart2_rxbuff[512] = {0};
static unsigned int __usart2_rxcnt = 0;
static unsigned int __usart2_rxflag = 0;

bool BLE::open(void){
    GPIO_Config_T gpio_configuration;
    USART_Config_T usart_configuration;
    System_setPeripheralClockEnable(CLK_GPIOA,TRUE);
    System_setPeripheralClockEnable(CLK_GPIOC,TRUE);
    System_setPeripheralClockEnable(CLK_USART2,TRUE);
    gpio_configuration.pin = GPIO_PIN_2;
    gpio_configuration.mode = GPIO_MODE_AF_PP;
    gpio_configuration.speed = GPIO_SPEED_50MHz;
    GPIO_Config(GPIOA,&gpio_configuration);
    gpio_configuration.pin = GPIO_PIN_3;
    gpio_configuration.mode = GPIO_MODE_IN_FLOATING;
    GPIO_Config(GPIOA,&gpio_configuration);
    gpio_configuration.pin = GPIO_PIN_3 | GPIO_PIN_4;
    gpio_configuration.mode = GPIO_MODE_OUT_PP;
    GPIO_Config(GPIOC,&gpio_configuration);
    /* Enter transparent transmission. */
    GPIO_SetBit(GPIOC,GPIO_PIN_3);
    GPIO_SetBit(GPIOC,GPIO_PIN_4);

    usart_configuration.baudRate = 115200;
    usart_configuration.hardwareFlow = USART_HARDWARE_FLOW_NONE;
    usart_configuration.mode = USART_MODE_TX_RX;
    usart_configuration.parity = USART_PARITY_NONE;
    usart_configuration.stopBits = USART_STOP_BIT_1;
    usart_configuration.wordLength = USART_WORD_LEN_8B;
    USART_Config(USART2,&usart_configuration);

    NVIC_EnableIRQRequest(USART2_IRQn,0,1);

    USART_EnableInterrupt(USART2,USART_INT_RXBNE);
    USART_EnableInterrupt(USART2,USART_INT_IDLE);
    USART_EnableTx(USART2);
    USART_EnableRx(USART2);
    USART_Enable(USART2);

    this->setStatus(true);
    return true;
}

bool BLE::close(void){
    GPIO_ResetBit(GPIOC,GPIO_PIN_3);
    GPIO_ResetBit(GPIOC,GPIO_PIN_4);
    USART_Disable(USART2);
    this->setStatus(false);
    return true;
}

int BLE::write(void *buff, int size) {
    int n = 0;
    unsigned char *data_ptr = reinterpret_cast<unsigned char*>(buff);
    const int timeout = 10000;  // 设置超时时间（循环次数）
    int timeout_counter = 0;    // 超时计数器

    for (n = 0; n < size; n++) {
        timeout_counter = 0;

        // 等待TX缓冲区空，或超时
        while (USART_ReadStatusFlag(USART2, USART_FLAG_TXBE) == RESET) {
            timeout_counter++;
            if (timeout_counter > timeout) {
                // 超时，返回失败
                return -1;  // 可以根据需求自定义错误码
            }
        }

        // 发送数据
        USART_TxData(USART2, data_ptr[n]);
    }

    return n;  // 返回成功写入的字节数
}

int BLE::read(void *buff,int size){

    int n = 0;
    unsigned char *data_ptr = reinterpret_cast<unsigned char*>(buff);
    for ( n = 0; n < __usart2_rxcnt && n < size; n++ ){
        data_ptr[n] = __usart2_rxbuff[n];
    }
    __usart2_rxcnt = 0;
    for ( int i = 0; i < 512; i++ ) __usart2_rxbuff[i] = 0;

    return n;
}

void BLE::setName(char *name){
    char txbuff[32];
    GPIO_ResetBit(GPIOC,GPIO_PIN_3);
    System_delayMs(200);
    sprintf(txbuff,"AT+NAME=%s\r\n",name);
    this->write(txbuff,strlen(txbuff));
    GPIO_SetBit(GPIOC,GPIO_PIN_3);
    System_delayMs(200);
}

int BLE::available(void){
    return __usart2_rxcnt;
}

void reverseBytes( char* buffer, int start, int length) {
    int end = start + length - 1;
    while (start < end) {
         char temp = buffer[start];
        buffer[start] = buffer[end];
        buffer[end] = temp;
        start++;
        end--;
    }
}

int current_cnt = 0;        //  BLE单次接收到的数据长度，当前测试每次是20
uint32_t total_cnt = 0;     //  BLE接收数据总长度
uint32_t data_size = 0;     //  协议包携带的数据长度信息
char target_rxbuff[512];    //  数据缓冲区
int offset = 0;             //  数据缓冲偏移量
void BLE::eventLoop(void){
    char rxbuff[512];
    int ret = 0;
    char error_buffer[3] = {0};
    if ( __usart2_rxflag ){
      
        current_cnt=this->read(rxbuff,this->available());

        //this->write(rxbuff,current_cnt);
        CommProtocolResponseHeader_t *ble_rec = (CommProtocolResponseHeader_t*)rxbuff;
        total_cnt = total_cnt + current_cnt;
        /* 检测到帧头 开始接收数据 */
        if(ble_rec->magic_number==0xAABB){
            offset = 0;
            total_cnt = 0;
            total_cnt = total_cnt + current_cnt;
            data_size = ble_rec->length + sizeof(CommProtocolResponseHeader_t);
        }
        if(total_cnt == data_size){
            memcpy(target_rxbuff + offset,rxbuff,current_cnt);
            ret = CommProtocol_parseRequest(target_rxbuff);
            /* 错误返回机制 首先将帧头格式以及相应的操作类型保存下来*/
            if(ret != 0){
                faultinfo->return_error(target_rxbuff,ret);
            }
        }
        else{
            memcpy(target_rxbuff + offset,rxbuff,current_cnt);
        }
        offset = offset + current_cnt;
        memset(rxbuff,0,512);
        __usart2_rxflag = 0;
    }
    return;
}

extern "C" __attribute__((interrupt()))
void USART2_IRQHandler(void){
    if ( USART_ReadIntFlag(USART2,USART_INT_RXBNE) != RESET ){
        __usart2_rxbuff[__usart2_rxcnt++] = USART_RxData(USART2);
        if ( __usart2_rxcnt >= 512 ) __usart2_rxcnt = 0;
    }
    if ( USART_ReadIntFlag(USART2,USART_INT_IDLE) != RESET ){
        USART_RxData(USART2);
        __usart2_rxflag = 1;
    }
}

bool BLE::getStatus(){
    if( is_enabled == true) return true;
    else return false;
}

void BLE::setStatus(bool status){
    this->is_enabled = status;
}